Skip to main content

Variable: VAR_GENERIC CONSTANT

Generic Constant Variable

Overview

The VAR_GENERIC extension provides support for generic constants at compile time in function blocks. This allows for the creation of flexible and reusable function blocks which can be adapted to different configurations (for example, buffer sizes or fixed ranges) without relying on dynamic memory allocation.

This feature is especially useful for function blocks which manage arrays or other memory structures. In addition, it allows for performance-optimized designs which are type-safe and fully resolved at compile time.

A generic constant is a variable in the VAR_GENERIC CONSTANT scope of a function block. The variable is defined only when the function block instance is declared.

Generic constants are allowed to be used in methods. This can be particularly helpful in the VAR_IN_OUT or VAR_IN_OUT CONSTANT scope.

Syntax

Declaration

Generic variables are declared between the keywords VAR_GENERIC CONSTANT and END_VAR in the declaration part of function blocks. All variables must be an integer data type (for example, INT, UINT, or DINT).

FUNCTION_BLOCK <function block name>
VAR_GENERIC CONSTANT
    <generic constant name> : <integer data type> := <initial value> ; //Initial value will be overwritten
END_VAR

<function block name>

Name of the function block

VAR_GENERIC CONSTANT

END_VAR

Scope for generic constants

You can declare any number of generic constants in the VAR_GENERIC CONSTANT scope.

<generic constant name>

Variable name of the generic constants

: <integer data type>

Construct which types the generic constant.

An integer data type or the subrange of an integer data type is permitted.

Example:

maxlen1 : INT := 4;

maxlen2 : INT(5..10) := 5;

:= <initial value>

Optional

Initialization

Important

The initial value is needed only for compile checks. At runtime, the value is overwritten.

Example:

FUNCTION BLOCK FB
VAR_GENERIC CONSTANT
    size : INT;
END_VAR
VAR
    buffer : ARRAY[0..size] OF BYTE;
END_VAR

Instantiation

A function block with generic constants can be instantiated via a parameter passing either explicitly as an expression or implicitly using a literal.

The following applies:

  • The part of the parameter passing which affects the VAR_GENERIC CONSTANT scope is enclosed in angle brackets.

  • Generic function blocks must be instantiated with parameters for all generic variables. The parameter passing must be complete. A partial specification is not permitted and will result in an error.

  • Either all parameters are specified explicitly, or all are specified implicitly. A mixture of explicit and implicit specifications is not permitted.

    • Implicit

      When parameters are passed for multiple generic variables, the desired values must be strung together as a literal and comma-separated in the order which they have been declared in the VAR_GENERIC CONSTANT scope.

      <5,10>
    • Explicit with name

      When parameters are passed for multiple generic variables, all of the desired parameters must be strung together as a bracketed expression and comma-separated in a free order. As usual, an expression is enclosed in parentheses.

      The expression assigns a literal, a variable, or an expression to the named generic constant using the assignment operator :=. It is important to enclose this explicit parameter transfer in parentheses.

      <(Array2Size := 10), (Array1Size := 5)>

      The advantage is that the parameter transfer is easily readable, therefore traceable and easily maintainable after changes.

  • If more variables have been declared, then additional parameters must be passed to them. Using the assignment operator :=, these are strung together and enclosed in parentheses.

Example 91. Example

Function block FB with generic constants

FUNCTION_BLOCK FB
VAR_GENERIC CONSTANT
    Array1Size : INT := 0;
    Array2Size : INT := 0;
END_VAR
VAR_INPUT
    MyArray1 : ARRAY[0..Array1Size-1] OF REAL;
    MyArray2 : ARRAY[0..Array2Size-1] OF REAL;
END_VAR
VAR
    SomeOtherParameter : INT;
END_VAR


Example 92. Example

Instantiation of the function block FB with simple parameter passing.

PROGRAM PLC_PRG
VAR
    MyFB1 : FB<5,10> := (SomeOtherParameter:=20);
END_VAR

VAR
    liArray1Size: LINT;
END_VAR
liArray1Size := UPPER_BOUND(MyFB1.MyArray1,1) + 1;


Example 93. Example

Function block instance MyFB2 with explicit parameter passing

PROGRAM PLC_PRG
VAR
    MyFB1 : FB<5,10> := (SomeOtherParameter:=20);
    MyFB2 : FB<(Array2Size:=10), (Array1Size:=5)> := (SomeOtherParameter := 10);
END_VAR

VAR
    Array1Size, Array2Size : LINT;
END_VAR
Array1Size := UPPER_BOUND(MyFB1.MyArray1,1) + 1;
Array2Size := UPPER_BOUND(MyFB1.MyArray2,1) + 1;


Inheritance with generic constants

Generic constants can also be passed to basic function blocks via inheritance.

Using constants in a function block

The constant can be used in a function block like any other constant (for example, in arrays or in string declarations). It can be used in methods, properties, or actions of the function block, but it cannot be accessed externally. This means that it behaves like a private variable.

Precompile checks

Because the final value of generic constants is not available in the function block, precompile checks are limited. It is possible to define an initialization value as follows:

FUNCTION_BLOCK FB
VAR_GENERIC CONSTANT  
    size : INT := 1;
END_VAR
VAR 
   buffer : ARRAY[0..size] OF BYTE;
END_VAR

This initialization value (value 1 in the example) is used for precompile checks within the function block, but it does not have any other effect.

Examples

Example 94. Example of using multiple generic constants
FUNCTION_BLOCK FB_Pou
VAR_GENERIC CONSTANT
    lnstring : DINT := 10;
    numstring : DINT := 100;
END_VAR
VAR
    arraystring : ARRAY[0..numstring-1] OF STRING(lnstring);
END_VAR
PROGRAM PLC_PRG
VAR
    fbPou : FB_Pou<100, 1000>;
END_VAR


Example 95. Example: Generic constant of a subrange type

A subrange type can be used as a generic parameter to specify a permitted range of values which is checked by the compiler.

FUNCTION_BLOCK FB_SrString 
VAR_GENERIC CONSTANT
    maxlen2 : INT(5..10) := 5;    //subrange data type
END_VAR
VAR
    arrTest : ARRAY[0..maxlen-1] OF BYTE;
END_VAR
;
PROGRAM SrMain
VAR CONSTANT
    cconst: INT(5..10) := 5;
END_VAR
VAR    
    fbMyString1 : FB_SrString<5>;
    fbMyString2 : FB_SrString<(2 * cconst)>;
    fbMyString3 : FB_SrcString<123>;
    // ERROR: An error is reported here because 123 is not within the value range 5..10.
    arrMyString : ARRAY [0..5] OF FB_SrString<6>;
END_VAR


Example 96. Example: Generic function block with parameterizable array variable

The following code demonstrates how to define a function block which can process arrays of arbitrary length. The function block has an array with a generic but constant length. "Constant" means that, although each function block instance varies in its array length, it is constant during the lifetime of the object.

This kind of construct is beneficial, for example, to a library programmer who wants to implement a generic library POU.

FUNCTION_BLOCK FB_MyString 
VAR_GENERIC CONSTANT
    maxlen : UDINT := 1;
END_VAR
VAR
    test : ARRAY[0..maxlen-1] OF BYTE;
END_VAR
PROGRAM PLC_PRG
VAR CONSTANT
    cconst: DINT := 1000;
END_VAR
VAR    
    fbMyString1 : FB_MyString<100>;
    fbMyString2 : FB_MyString<(2 * cconst)>;   
    arrMyString : ARRAY[0..5] OF FB_MyString<6>;    
END_VAR


Inheritance

A function block can inherit from a base function block with a generic constant (EXTENDS). The inheriting function block requires its own generic constant. A specific value can then be transferred externally.

Syntax:

FUNCTION_BLOCK <function block name> 
VAR_GENERIC CONSTANT        
    <generic constant name> : <integer data type> ; 
END_VAR 
EXTENDS <function block base> < <generic constant name> >

A function block with a generic constant can implement an interface (IMPLEMENTS). The interface declares a property (PROPERTY) with which the specified value can be accessed externally. The interface itself must not declare any generic constants or local variables. Interfaces have no implementation.

Syntax:

FUNCTION_BLOCK <function block name>
VAR_GENERIC CONSTANT
    <generic constant name> : <integer data type> ;
END_VAR
IMPLEMENTS <interface name>

Important

When coding, make sure that the declaration of the generic constants is inserted first, followed by EXTENDS and IMPLEMENTS. This takes some getting used to, but the reason is that generic constants can also be used with base classes.

Example 97. Example

Definition of the IString interface for a generic function block.

It is strongly recommended to define an interface for generic function blocks. The interface should allow the generic function block instance to be used without knowledge of the generic constants.

The Length property enables access to the generic constant.

INTERFACE IString 
METHOD Append : BOOL 
VAR_INPUT     
    strAppend : IString; 
END_VAR 

METHOD Assign : BOOL
VAR_INPUT     
    stringIn : STRING; 
END_VAR 

METHOD ToString : STRING
VAR_INPUT 
END_VAR 

PROPERTY Length : DINT

Declaration of the function block FB_MyString with the generic constant maxlen

FUNCTION_BLOCK FB_MyString 
VAR_GENERIC CONSTANT        
    maxlen : UDINT; 
END_VAR 
IMPLEMENTS IString 

The function block FB_LongString is an extension of the specified function block FB_MyString.

FUNCTION_BLOCK FB_LongString EXTENDS FB_MyString<1000>

Declaration of the function block FB_MySpecialString with the generic constant maxlen2 as an extension of the specified function block FB_MyString. The function block is extended by the method METH_ToLatin.

FUNCTION_BLOCK FB_MySpecialString 
VAR_GENERIC CONSTANT        
    maxlen2 : UDINT:= 1; 
END_VAR 
EXTENDS FB_MyString<maxlen2>
METHOD METH_ToLatin : STRING
VAR_INPUT
END_VAR

Instantiation of the function blocks with specific constants

PROGRAM PLC_PRG 
VAR CONSTANT     
    cconst: DINT := 1000; 
END_VAR
VAR     
    string1 : FB_MyString<100>;
    string2 : FB_MyString<(2 * cconst)>;
    derived1 : FB_LongString;
    derived2 : FB_MySpecialString<100>;
END_VAR 

Calls

string1.METH_Assign ('Welt'); 
string2.METH_Assign ('Hallo '); 
string2.METH_Append(string1); 
derived2.METH_ToLatin('Hello World');